package servidor;
import java.util.Collections;
import java.util.HashMap;
import java.util.Vector;

import comum.CartaComum;
import comum.Mesa;
import java.util.HashSet;
import java.util.LinkedHashSet;

public final class RN_Partida {
	
    public static final int NUM_JOGADORES = 4;
    private static final RN_Partida INSTANCE = new RN_Partida();
    private int numeroDePassaVez = 0;

    private Vector<RN_JogadorConectado> jogadoresConectados = new Vector<RN_JogadorConectado>(); 
    
    //A mesa nao era criada em nenhum momento
    //Como foi preciso acessa-la, pra descobrir qual era o jogador vencedor
    //Coloquei o metodo de acesso getMesa()
    //Alem disso, como esta classe RN_Partida eh singleton, 
    //apenas a mesa pertencente a esta RN_Partida sera criada
    private Mesa mesa = new Mesa(); 
    
    private IP_Ranking ranking;
    private int jogadorDaVez;

    private RN_Partida() {
        if (INSTANCE != null) {
            throw new IllegalStateException("Already Instantiated");
        }
    }

    public static RN_Partida getRN_Partida() {	
        return INSTANCE;			
    }

    public void adicionarJogador(String nomeJogador) {
        getJogadoresConectados().add(new RN_JogadorConectado(nomeJogador));
              
        if (isSalaCheia()) {
            this.iniciarPartida();
        }
    }

    private void iniciarPartida() {	
        //ranking = new IP_Ranking(); //padrao DAO
        
        RN_Baralho.getRN_Baralho().embaralharCartas();
        RN_Baralho.getRN_Baralho().distribuirCartas(getJogadoresConectados());
        Collections.shuffle(getJogadoresConectados());

        setJogadorDaVez(0);
        getMesa().setJogadorDaVez(getJogadoresConectados().get(getJogadorDaVez()).getJogador().getNome());

        for(RN_JogadorConectado jogadorConectado : getJogadoresConectados()) {
                getMesa().setNumeroDeCartasDoJogador
                        (jogadorConectado.getJogador().getNome(),
                                        jogadorConectado.getJogador().getMaoDeCartas().size());
        }
        Thread t = new Thread(){
            @Override
            public void run(){
                SO_PresidenteServidor.getServidor().iniciarPartida(getMesa());
            }
        };
        t.start();
    }

    private boolean isPartidaTerminada() {
        //checa condicoes de termino
        //apenas ultimo jogador a jogar pode ter vencido o jogo.
                //caso contrario jogo deveria ter terminado mais cedo

        return getJogadoresConectados().get(getJogadorDaVez()).getJogador().isMaoVazia();
    }

    public boolean isSalaCheia() {
        return getJogadoresConectados().size() == NUM_JOGADORES;
    }

    public void notificarFimDaPartida(HashMap<String, Integer> ranking) {
        SO_PresidenteServidor.getServidor().terminarPartida(getMesa(),ranking);
        SO_PresidenteServidor.getServidor().desconectarJogadoresAposFim();
        RN_Partida.getRN_Partida().resetarPartida();

    }


    public void fazerJogada( HashSet<CartaComum> selecao) {
        
        if(selecao.size() == 0) {
            numeroDePassaVez++;
        }
        if(numeroDePassaVez >= (NUM_JOGADORES-1)) {
            numeroDePassaVez = 0;
            getMesa().setUltimoDescarte(new LinkedHashSet<CartaComum>());
        }
        
        if(selecao.size() > 0){
            getJogadoresConectados().get(getJogadorDaVez()).atualizarMaoDeCartas(selecao);
            getMesa().atualizarMesa(selecao);
            numeroDePassaVez = 0;
        }
        
        if (isPartidaTerminada()) {

            HashMap<String, Integer> novoRanking = (new IP_Ranking()).atualizarObterRanking();
            SO_PresidenteServidor.getServidor().atualizarMesa(getMesa());
            //notificarFimDaPartida(new HashMap<String,Integer>());
            notificarFimDaPartida(novoRanking);
            return ;
        }
        setJogadorDaVez((getJogadorDaVez() + 1) % NUM_JOGADORES);
        getMesa().setJogadorDaVez(getJogadoresConectados().get(getJogadorDaVez()).getJogador().getNome());
        
        SO_PresidenteServidor.getServidor().atualizarMesa(getMesa());			
    }

    public Mesa getMesa() {
        return mesa;
    }

    public void setMesa(Mesa mesa) {
        this.mesa = mesa;
    }

    public Vector<RN_JogadorConectado> getJogadoresConectados() {
        return jogadoresConectados;
    }

    public void setJogadoresConectados(Vector<RN_JogadorConectado> jogadoresConectados) {
        this.jogadoresConectados = jogadoresConectados;
    }   
    
    public int getJogadorDaVez() {
        return jogadorDaVez;
    }

    public void setJogadorDaVez(int jogadorDaVez) {
        this.jogadorDaVez = jogadorDaVez;
    }    
    
    public void resetarPartida() {
    	getMesa().resetarMesa();

        try {
            RN_Baralho.getRN_Baralho().resetarBaralho();
        } catch (NullPointerException e) {
        }
    	
    	setJogadoresConectados(new Vector<RN_JogadorConectado>()); 
    
    }
       
}
